#pragma once
#include <vector>
#include <string>
#include<iostream>
using namespace std;

//仿函数--> 将非整型数据转换为整型
template<class K>
struct HashFunc
{
	size_t operator()(const K& key)
	{
		return key;
	}
};

template<>
struct HashFunc<string>
{
	size_t operator()(const string& s)
	{
		size_t hash = 0;
		for (auto ch : s)
		{
			hash += ch;
			hash *= 31;
		}
		return hash;
	}
};


namespace HashBucket
{
	//1.节点
	template<class T>
	struct HashNode
	{
		HashNode<T>* _next;
		T _data;

		HashNode(const T& data)
			:_next(nullptr)
			, _data(data)
		{}
	};

	
	// 前置声明
	template<class K, class T, class KeyOfT, class Hash>
	class HashTable;

	//2.迭代器
	template<class K, class T, class Ref, class Ptr, class KeyOfT, class Hash>
	struct __HashIterator
	{
		typedef HashNode<T> Node;
		typedef HashTable<K, T, KeyOfT, Hash> HT;
		typedef __HashIterator<K, T, Ref, Ptr, KeyOfT, Hash> Self;
		typedef __HashIterator<K, T, T&, T*, KeyOfT, Hash> Iterator;

		//节点 + 哈希表
		Node* _node;
		const HT* _ht;

		//构造函数
		__HashIterator(Node* node, const HT* ht)
			:_node(node)
			, _ht(ht)
		{}
		//普通迭代器构造const迭代器
		__HashIterator(const Iterator& it)
			:_node(it._node)
			, _ht(it._ht)
		{}

		//重载运算符 *  ->  ==  !=  ++  
		Ref operator*() { return _node->_data; }
		Ptr operator->() { return &(_node->_data); }
		bool operator==(const Self& it) { return _node == it._node; }
		bool operator!=(const Self& it) { return _node != it._node; }

		Self& operator++()
		{
			//1.如果下一个节点不为nullptr返回下一个节点
			if (_node->_next)
			{
				_node = _node->_next;
			}
			//2.找下一个不为空的桶
			else
			{
				//计算当前桶的位置
				Hash hash; KeyOfT kot;
				size_t hashi = hash(kot(_node->_data)) % _ht->GetCapacity();
				vector<Node*> tables = _ht->GetTables();
				++hashi;
				//找到不为空的桶
				while (hashi < _ht->GetCapacity())
				{
					if (tables[hashi])
					{
						_node = tables[hashi];
						break;
					}
					else
					{
						++hashi;
					}
				}
				//找完没有下一个节点就返回空指针
				if (hashi == _ht->GetCapacity()) _node = nullptr;
			}
			return *this;
		}
	};

	//3.哈希表
	template<class K, class T, class KeyOfT, class Hash>
	class HashTable
	{
		typedef HashNode<T> Node;
	public:
		typedef __HashIterator<K, T, T&, T*, KeyOfT, Hash> iterator;
		typedef __HashIterator<K, T, const T&, const T*, KeyOfT, Hash> const_iterator;

		iterator begin()
		{
			//找第一个有元素的哈希桶
			size_t hashi = 0;
			while (hashi < GetCapacity())
			{
				if (_tables[hashi] != nullptr)
				{
					return iterator(_tables[hashi], this);
				}
				++hashi;
			}
			return iterator(nullptr, this);
		}

		iterator end()
		{
			return iterator(nullptr, this);
		}

		const_iterator begin() const
		{
			Node* cur = nullptr;
			//找第一个有元素的哈希桶
			size_t hashi = 0;
			while (hashi < GetCapacity())
			{
				if (_tables[hashi] != nullptr)
				{
					return iterator(_tables[hashi], this);
				}
				++hashi;
			}
			return iterator(nullptr, this);
		}

		const_iterator end() const
		{
			return const_iterator(nullptr, this);
		}

		//接口 insert   +  find   +  erase
		iterator Find(const K& key)
		{
			//桶中没有元素直接返回
			if (_tables.size() == 0)
				return end();
			//计算桶的位置 + 直接在桶里面找
			KeyOfT kot; Hash hash;
			size_t hashi = hash(key) % _tables.size();
			Node* cur = _tables[hashi];
			while (cur)
			{
				if (kot(cur->_data) == key)
				{
					return iterator(cur, this);
				}

				cur = cur->_next;
			}
			return end();
		}

		pair<iterator, bool> Insert(const T& data)
		{
			//找到,插入失败
			KeyOfT kot; Hash hash;
			iterator it = Find(kot(data));
			if (it != end())
			{
				return make_pair(it, false);
			}

			// 扩容
			if (_n == _tables.size())
			{
				size_t newsize = _tables.size() == 0 ? 10 : 2 * _tables.size();
				vector<Node*> newtables(newsize, nullptr);
				for (auto& cur : _tables)
				{
					//将旧的数据移动到新表
					while (cur)
					{
						//重新计算桶的位置
						Node* next = cur->_next;
						size_t hashi = hash(kot(cur->_data)) % newtables.size();
						cur->_next = newtables[hashi];
						newtables[hashi] = cur;
						cur = next;
					}
				}
				//交换新旧表
				_tables.swap(newtables);
			}

			size_t hashi = hash(kot(data)) % _tables.size();
			// 头插
			Node* newnode = new Node(data);
			newnode->_next = _tables[hashi];
			_tables[hashi] = newnode;
			++_n;

			return make_pair(iterator(newnode, this), true);;
		}

		bool Erase(const K& key)
		{
			Hash hash; KeyOfT kot;
			//算当前桶的位置
			size_t hashi = hash(key) % _tables.size();
			Node* prev = nullptr;
			Node* cur = _tables[hashi];
			while (cur)
			{
				if (kot(cur->_data) == key)
				{
					//头删
					if (prev == nullptr)
					{
						_tables[hashi] = cur->_next;
					}
					//非头删
					else
					{
						prev->_next = cur->_next;
					}
					delete cur;

					return true;
				}
				else
				{
					prev = cur;
					cur = cur->_next;
				}
			}
			return false;
		}

		//析构函数
		~HashTable()
		{
			for (auto& cur : _tables)
			{
				while (cur)
				{
					Node* next = cur->_next;
					delete cur;
					cur = next;
				}

				cur = nullptr;
			}
		}
		//给迭代器提供接口-->获取哈希桶的个数  +  哈希表
		size_t GetCapacity() const
		{
			return _tables.size();
		}

		vector<Node*> GetTables() const
		{
			return _tables;
		}

	private:
		vector<Node*> _tables; // 指针数组
		size_t _n = 0; // 存储有效数据个数
	};

}